# from data.data_parser import *
import logging
import sys
import time

from PyQt5 import QtWidgets

from data.DataHandler import datahandler
from data.UDP_multicast import UDPMulticast
from data.qtutils import *
import struct
from data.defines import *

GPS_HEAD = 0xAA55  # 数据帧头
GPS_END = 0x5AA5  # 数据帧尾

# gps发送端口文件名
target_ports_filename = 'gps_port.txt'  # 保存GPS网口组播IP,上行端口号
file_path_mac = os.getcwd() + '/'
file_path_win = os.getcwd() + '\\'


# 顶部菜单，参数遥调
class PosSendPad(QWidget):
    # 开始或者停止计时器
    timer_start = pyqtSignal()
    timer_stop = pyqtSignal()

    def __init__(self):
        super().__init__()

        self.setWindowTitle('GPS发送')
        self.setMinimumWidth(500)
        self.initui()
        self.lon = 113.1231244
        self.lat = 32.0123904
        self.alt = 1232
        self.count = 0
        self.tag_stop = False

        # 发送的timer，并绑定定时器开关
        self.send_gps_timer = QTimer()
        self.send_gps_timer.timeout.connect(self.send_request)
        self.send_gps_timer.setInterval(1000)
        self.timer_start.connect(self.send_gps_timer.start)
        self.timer_stop.connect(self.send_gps_timer.stop)

        self.connect = None
        datahandler.sig_RecvSensorINS.connect(self.recvFccData)

    def initui(self):
        grid = QGridLayout()
        grid.setSpacing(10)
        self.setLayout(grid)

        reg_valid = ['', '^-?(180|((1[0-7]\d|\d?\d)(\.\d{0,7})?))$',
                     '^-?(90|(([1-8]\d|\d)(\.\d{0,7})?))$',
                     '^10000|(((\d{0,4})?)(\.\d{0,2})?)$']  # '^2000|1\d{3}|[1-9]?\d?\d$'  '^10000|((\d?{4})(\.\d{0-2}?))$'

        label = QLabel('端口号')
        grid.addWidget(label, 0, 0)
        self.edit_gps_udp_port = QLineEdit()
        grid.addWidget(self.edit_gps_udp_port, 0, 1, 1, 2)

        current = os.getcwd()
        if current.startswith('/'):
            filename = file_path_mac + target_ports_filename
        else:
            filename = file_path_win + target_ports_filename
        if os.path.exists(filename):
            with open(filename, 'r') as fr:
                port = fr.readline().strip()
                if len(port) > 0:
                    self.edit_gps_udp_port.setText(port)

        btn_open = QPushButton('连接')
        btn_open.clicked.connect(lambda: self.click_btn_open())
        grid.addWidget(btn_open, 0, 3)

        btn_close = QPushButton('断开')
        btn_close.clicked.connect(lambda: self.click_btn_close())
        grid.addWidget(btn_close, 0, 4)

        btn_send = QPushButton('发送')
        btn_send.clicked.connect(lambda: self.click_btn_send())
        grid.addWidget(btn_send, 0, 5)

        btn_stop = QPushButton('停止')
        btn_stop.clicked.connect(lambda: self.click_btn_stop())
        grid.addWidget(btn_stop, 0, 6)

        btn_continue = QPushButton('继续')
        btn_continue.clicked.connect(lambda: self.click_btn_continue())
        grid.addWidget(btn_continue, 0, 7)

        label = QLabel('经度')
        grid.addWidget(label, 1, 0)
        self.edit_gps_lon = QLineEdit()
        self.edit_gps_lon.setValidator(QRegExpValidator(QRegExp(reg_valid[1])))
        grid.addWidget(self.edit_gps_lon, 1, 1, 1, 2)

        label = QLabel('纬度')
        grid.addWidget(label, 1, 3)
        self.edit_gps_lat = QLineEdit()
        self.edit_gps_lat.setValidator(QRegExpValidator(QRegExp(reg_valid[2])))
        grid.addWidget(self.edit_gps_lat, 1, 4, 1, 2)

        label = QLabel('高度')
        grid.addWidget(label, 1, 6)
        self.edit_gps_alt = QLineEdit()
        self.edit_gps_alt.setValidator(QRegExpValidator(QRegExp(reg_valid[3])))
        grid.addWidget(self.edit_gps_alt, 1, 7, 1, 2)

        self.label_count = QLabel('计数')
        grid.addWidget(self.label_count, 0, 8)

    # 连接云台
    def connect_dlink(self, udp_ip: str, up_port: int, down_port: int):
        """
        连接云台；连接成功后程序的其他内容启动

        :param udp_ip: 组播地址
        :param up_port: 上传端口
        :param down_port: 下载端口
        """
        # 开始连接port端口
        self.udp_ip = udp_ip
        self.up_port = up_port
        self.down_port = down_port

        if self.connect is None:
            # print('connect:', threading.current_thread())
            count = 5
            while count > 0:
                time.sleep(0.1)
                count -= 1
                self.connect = PosSendPad.connect_udp_port(self.udp_ip, self.up_port, self.down_port)
                # print(self.connect)
                if self.connect is not None:
                    self.timer_start.emit()
                    break

    @staticmethod
    def connect_udp_port(udp_ip: str, up_port: int, down_port: int):
        """
        连接udp端口

        :param udp_ip: 组播地址
        :param up_port: 上传端口
        :param down_port: 下载端口
        :return: udp实例:表示已经连接上云台；None:连接失败
        """
        # 检测网口是否是飞控的数据
        # 建立网口实例，打开网口
        udp_socket = UDPMulticast(udp_ip, up_port, down_port)
        # print('创建成功')
        con = None

        try:
            # 建立套接字，设置超时
            udp_socket.establish_udp_multicast_socket(1)
            # data = udp_socket.receive_data(5)
            # print(data)
            con = udp_socket
        except Exception:
            pass
        return con

    def click_btn_open(self):
        info = self.edit_gps_udp_port.text().strip()
        if len(info) == 0:
            QMessageBox.information(self, 'info', '请输入网口连接参数！', QMessageBox.Ok)
            return
        info_arr = info.split('/')
        if len(info_arr) < 2:
            QMessageBox.information(self, 'info', '请输入网口连接参数！', QMessageBox.Ok)
            return
        try:
            # print(self.connect)
            self.connect_dlink(str(info_arr[0]), int(info_arr[1]), 20002)
            self.count = 0
            self.label_count.setText(str(self.count))
            # print('连接成功')

            current = os.getcwd()
            filepath = file_path_win
            if not os.path.exists(filepath):
                os.makedirs(filepath)
            with open(filepath + target_ports_filename, 'w') as fw:
                fw.write(info)
        except Exception as e:
            QMessageBox.information(self, 'info', '请输入网口连接参数！', QMessageBox.Ok)

    def click_btn_close(self):
        self.timer_stop.emit()  # 关掉定时器
        if self.connect is not None:
            self.connect.close_socket()  # 关掉网口连接
            self.connect = None
            # print('断开')

    def click_btn_send(self):
        a = self.edit_gps_lon.text()
        b = self.edit_gps_lat.text()
        c = self.edit_gps_alt.text()
        if self.check_input(a, b, c):
            lon = float(self.edit_gps_lon.text().strip())
            lat = float(self.edit_gps_lat.text().strip())
            alt = float(self.edit_gps_alt.text().strip())
            data = struct.pack('=H2B3lH', GPS_HEAD, 0x01, 0x0C, int(lon * 1e7), int(lat * 1e7), int(alt * 1e3), GPS_END)
            # print(data)
            if self.connect is not None:
                self.connect.send_data(data)
                self.count = self.count + 1
                self.label_count.setText(str(self.count))
            # print('单次发送')

    def click_btn_stop(self):
        if self.tag_stop is False:
            self.timer_stop.emit()  # 关掉定时器
            self.tag_stop = True
            self.count = 0
            self.label_count.setText(str(self.count))
            # print('停止发送')

    def click_btn_continue(self):
        if self.tag_stop is True:
            self.timer_start.emit()  # 开启定时器
            self.tag_stop = False
            # print('继续发送')

    # 定时器到点之后实际执行发送请求的方法
    def send_request(self):
        data = struct.pack('=H2B3lH', GPS_HEAD, 0x01, 0x0C, int(self.lon * 1e7), int(self.lat * 1e7),
                           int(self.alt * 1e3), GPS_END)
        # print(data)
        if self.connect is not None:
            self.connect.send_data(data)
            self.count = self.count + 1
            self.label_count.setText(str(self.count))
            self.edit_gps_lon.setText("%.7f" % self.lon)
            self.edit_gps_lat.setText("%.7f" % self.lat)
            self.edit_gps_alt.setText("%.1f" % self.alt)
            # print('定时发送')

    def recvFccData(self, data):
        try:
            self.lon = data["lon_deg"]
            self.lat = data["lat_deg"]
            self.alt = data["alt_m"]
            # print(self.lon)
            # print(self.lat)
            # print(self.alt)

        except Exception as e:
            logging.error(repr(e))

    def check_input(self, *args):
        rs = True
        for s in args:
            if s is None or len(s.strip()) == 0:
                rs = False
                QMessageBox.information(self, 'info', '数据不完整！', QMessageBox.Ok)
                break

        return rs


# 地面站软件的入口程序
if __name__ == '__main__':
    # 启动地面站主界面
    app = QtWidgets.QApplication(sys.argv)
    gcs_main_window = QtWidgets.QMainWindow()
    ui = PosSendPad()
    # ui.setupUi(gcs_main_window)
    # ui.gui_init()
    # gcs_main_window.show()  # 显示窗口
    ui.show()
    # ui.close()
    sys.exit(app.exec_())
